package com.by.token;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.by.autoconfig.TokenProperties;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * token工具类  生成token 验证token  刷新token
 */
public class TokenTemplate {

    @Autowired
    TokenProperties properties;

    /**
     * 生成token
     *
     * @return
     */
    public String generateToken(Map<String, Object> payloadClaims) {
        return JWT.create()
                .withHeader(getHeader())
                .withPayload(payloadClaims)
                .withExpiresAt(getExpireDate())//指定在将来某个时间点过期
                .sign(getAlgorithm());
    }

    /**
     * 验证token
     *
     * @param token 要验证的token字符串
     * @return 1  token无效  2 token过期  3 token有效
     */
    public int verifyToken(String token) {
        // 根据密钥生成验证类
        JWTVerifier verifier = JWT.require(getAlgorithm())
                .build();
        //验证token
        DecodedJWT decodedJWT = null;
        try {
            decodedJWT = verifier.verify(token);
        } catch (Exception e) {
            String msg = e.getMessage();
            if (msg.indexOf("Token has expired") > 0) {
                return 2;
            } else {
                return 1;
            }
        }
        return 3;
    }

    /**
     * 获取算法
     *
     * @return
     */
    Algorithm getAlgorithm() {
        return Algorithm.HMAC256(properties.getSecret());
    }


    /**
     * 获取指定token的有效信息
     *
     * @param token
     * @return
     */
    public Map getPayload(String token) {
        //验证token是否有效
        int rs = verifyToken(token);
        if (rs != 3)
            return null;
        DecodedJWT decodedJWT = JWT.decode(token);
        return decodedJWT.getClaims();
    }


    /**
     * 设置token有效时间  默认30分钟
     *
     * @return
     */
    Date getExpireDate() {
        //获取当前系统的毫秒时间
        long begin = System.currentTimeMillis();
        //计算半小时后的毫秒时间
        long time = begin + this.properties.getTimes() * 60 * 1000;
        return new Date(time);
    }

    /**
     * jwt头部
     *
     * @return
     */
    Map getHeader() {
        Map<String, String> header = new HashMap<>();
        header.put("typ", "JWT");
        header.put("alg", "HMAC256");
        return header;
    }

}
